A participação virtual deixa uma conta do Treino Livre refazer um contest que já terminou. A prova roda no tempo de quem participa. Os times oficiais aparecem como "fantasmas": cada um resolve cada problema no mesmo minuto em que resolveu na prova real. No fim, a linha do participante fica gravada no placar virtual do contest, marcada como virtual.
Página: /treino/virtual/?c=<contest> (site
principal). Código: server/api/v1/lib/virtual.sh,
handlers/treino/virtual/*,
web/treino/virtual/,
web/shared/virtual-board.js.
| Plataforma | O que faz | O que o MOJ copiou | O que o MOJ mudou |
|---|---|---|---|
| Codeforces | Botão em toda prova encerrada. Regras de honra. Horário de início.
Placar no tempo relativo. Uma participação por prova. Cancela só antes
de qualquer ação. Linha marcada com #. |
Regras de honra, horário de início, placar no tempo relativo, uma vez por conta, linha marcada. | Desistência explícita (ver §4): virtual abandonado não polui o placar. |
| AtCoder | A aba "Virtual Standings" anda no tempo virtual, mas a aba "Standings" mostra o resultado final. | — | Um placar só, sempre no tempo do participante. |
O dono liga o módulo virtual (Central ›
Módulos). O portão vr_load confere todas
as condições a cada requisição:
virtual ligado;SECRET);contest_over_for_all: fim + maior prorrogação);FREEZE_TIME
= 0 — o "Encerrar evento" faz isso);contests/treino/var/jsons/<id>.json com
public != false).Participação virtual de problema privado não existe.
Nada do virtual lê jsons-private/ nem
MOJ_PROBLEMS_DIR. O enunciado vem da rota pública
/treino/problem?id=.
virtual_unavailable em todas as rotas, com corpo
idêntico ao de contest inexistente. A resposta não
confirma existência, fase, título nem número de problemas.virtual_not_eligible; a mensagem dá só a
contagem, nunca o id.server/test/smoke-virtual-leak.sh (matriz rota
× contest proibido, 365 asserções)..admin, .judge…) não participa.CONTEST_END − CONTEST_START do conf.virtual:"<cid>" no
/submit. Spool, juiz, report e perfil não mudam. O servidor
exige: run rodando, problema da prova, linguagem permitida no
contest.PENALTY_MINUTES, PENALTY_VERDICTS).contests/<c>/users/. Placar
oficial, estatística, relatório, webcast e rodadas não
mudam.| Arquivo | Conteúdo |
|---|---|
contests/treino/users/<login>/virtual/<cid>.json |
estado da run (autoritativo; acompanha o rename) |
contests/treino/users/<login>/virtual/<cid>.subs |
subids etiquetados |
contests/<cid>/virtual/runs/<login>.json |
snapshot gravado ao finalizar (imune a rejulgamento) |
contests/<cid>/var/virtual-feed.json(.gz) |
feed dos fantasmas (cache) |
contests/<cid>/var/virtual-board.json |
agregado dos snapshots (cache) |
| Situação | Resultado |
|---|---|
| Rodando, ≤ 15 min de prova ou nenhum Accepted | botão Desistir: nada é gravado e a tentativa volta |
| Rodando, > 15 min e ≥ 1 Accepted | não dá mais para desistir; o resultado será gravado |
| Tempo acabou com 0 Accepted | descartada sozinha; conta como desistência |
| Encerrar agora com 0 Accepted | vira desistência |
| Já desistiu 2 vezes | a próxima largada é definitiva: sem desistir, grava mesmo com 0 |
As submissões de uma run descartada continuam no histórico do treino.
Constantes: VR_GRACE_S (900), VR_MAX_DISCARDS
(2), VR_SCHEDULE_MAX_S (7 d), VR_PENDING_MAX_S
(1 h: pendente mais velho que isso não segura a finalização).
GET /treino/virtual/feed entrega os times do
placar público final (var/placar.txt:
coorte pública, desclassificados e papéis já filtrados) e todas as runs
[seg, time, problema, Y|N|X|?].web/shared/virtual-board.js reconstrói o placar em
qualquer instante t e devolve o mesmo
objeto que parseICPC; o renderizador do placar
oficial o desenha.web/contest/score/score-filters.js, fonte única com o
placar ao vivo. Os dados vêm das rotas públicas
/contest/teams, /contest/teams-meta e
/contest/regions. A escolha fica lembrada no navegador, por
contest.
boardAt … {teamOk}): posição e ★ saem iguais às do placar
próprio daquela visão no servidor. O feed traz views[] e a
coorte de cada time — só coortes públicas com time no
placar público.sliceVirtualPlaces) e nunca recebe ★.GET/POST /treino/virtual/friends, arquivo
treino/users/<login>/virtual/_friends.json (o
_ impede colisão com o estado de um contest). Sem login a
lista fica no navegador e é mesclada na conta no primeiro acesso logado.
Teto de 100 logins. A rota não confere se a conta existe (seria oráculo
de existência). O rename de conta reescreve as listas que citam o login
antigo.smoke-virtual-board.gjs.sh:
motor em t=∞ == placar.txt; motor em
t=T == placar de history truncado.Evento › Virtual: mostra o portão aberto em partes
(o que falta), o link da página e as participações gravadas.
remove/restore tiram ou devolvem uma linha
(auditado). Rota: /contest/admin/virtual.
Devolver a tentativa (reset): para um
testador, ou para quem teve problema. A ação apaga a linha gravada e põe
de lado o estado da conta naquele contest (as
desistências também). A conta pode largar de novo. A regra "uma vez por
conta" continua para todos os outros. As submissões ficam no histórico
do treino. A ação é auditada (virtual-reset).
Times virtuais; placar OBI/heurístico; rodadas arquivadas;
moj-comp --virtual; ver ao vivo outras participações
virtuais em andamento.